#include "EffectLoader.h"

EffectLoader::EffectLoader(void)
: m_variablesActive(false), m_parsingVariable(false), m_parsingGuiControl(false)
{
}

EffectLoader::~EffectLoader(void)
{
}

Effect EffectLoader::load(const QString &filename)
{
	QXmlSimpleReader reader;

	QFile file(filename);
	if(!file.open(QFile::ReadOnly))
	{
		QMessageBox message;
		message.setText("Failed to open: " + filename);
		message.exec();
	}

	QXmlInputSource* source = new QXmlInputSource(&file);

	reader.setContentHandler(this);
	reader.setErrorHandler(this);

	reader.parse(source);

	Effect effect;

	effect.setName(m_name);
	effect.setGLSLFilename(m_glslFilename);

	foreach(EffectVariable var, m_variables)
	{
		effect.addVariable(var);

		/*EffectVariable& theNewVar = effect->addVariable();
		theNewVar = var;
		if(theNewVar.hasGuiControl)
		{
			setupVariableGui(theNewVar, m_variableGuiControlsDefs[theNewVar.name], mainLayout, obj);
		}*/
	}

	return effect;
}
/*
void EffectLoader::setupVariableGui(EffectVariable& var, const EffectVariableGuiControlDefinition& def, QVBoxLayout* mainLayout, QObject* obj)
{
	var.guiControl.type = def.type;

	if(def.type == EffectVariableGuiControlType::CheckBox)
	{
		var.guiControl.widget = new QGroupBox;

		QCheckBox* checkBox = new QCheckBox;
		checkBox->setText(def.checkBox.text);
		checkBox->setChecked(def.checkBox.pressedByDefault);

		QVBoxLayout* layout = new QVBoxLayout;
		layout->addWidget(checkBox);

		var.guiControl.widget->setLayout(layout);

		QObject::connect(checkBox, SIGNAL(pressed()), obj, SLOT(buttonPressed()));
	}
	else if(def.type == EffectVariableGuiControlType::Slider)
	{
		var.guiControl.widget = new QGroupBox(def.slider.title);
		QGroupBox* groupBox = static_cast<QGroupBox*>(var.guiControl.widget);

		QSlider* slider = new QSlider();
		slider->setMinimum(def.slider.min);
		slider->setMaximum(def.slider.max);
		slider->setValue(def.slider.default);
		slider->setOrientation(Qt::Horizontal);

		QVBoxLayout* layout = new QVBoxLayout;
		layout->addWidget(slider);

		groupBox->setLayout(layout);

		QObject::connect(slider, SIGNAL(sliderMoved(int)), obj, SLOT(sliderMoved(int)));
	}
	else if(def.type == EffectVariableGuiControlType::RadioButtons)
	{
		var.guiControl.widget = new QGroupBox(def.radioButtons.title);

		QButtonGroup* buttonGroup = new QButtonGroup;

		QVBoxLayout* layout = new QVBoxLayout();

		foreach(EffectVariableRadioButtonsEntry entry, def.radioButtons.entries)
		{
			QRadioButton* button = new QRadioButton();
			button->setText(entry.text);
			if(entry.isDefault)
			{
				button->setChecked(true);
			}

			buttonGroup->addButton(button);
			layout->addWidget(button);
		}

		QObject::connect(buttonGroup, SIGNAL(buttonPressed(QAbstractButton*)), obj, SLOT(buttonPressed(QAbstractButton*)));

		var.guiControl.widget->setLayout(layout);
	}

	mainLayout->addWidget(var.guiControl.widget);
}
*/

bool EffectLoader::startElement(const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts)
{
	if(qName == "Effect")
	{
		QString effectName = atts.value("name");
		m_name = effectName;
	}
	else if(qName == "GLSL")
	{
		QString sourceFilename = atts.value("filename");
		m_glslFilename = sourceFilename;
	}
	else if(qName == "Variables")
	{
		if(!m_variablesActive)
			m_variablesActive = true;
	}
	else if(qName == "Float")
	{
		if(!m_parsingVariable)
		{
			m_parsingVariable = true;

			QString variableName = atts.value("name");
			float variableValue = atts.value("defaultValue").toFloat();

			m_currentVariable.value.type = EffectVariableType::Float;
			m_currentVariable.name = variableName;
			m_currentVariable.value.floatValue = variableValue;
		}
	}
	else if(qName == "Integer")
	{
		if(!m_parsingVariable)
		{
			m_parsingVariable = true;

			QString variableName = atts.value("name");
			int variableValue = atts.value("defaultValue").toInt();

			m_currentVariable.value.type = EffectVariableType::Int;
			m_currentVariable.name = variableName;
			m_currentVariable.value.intValue = variableValue;
		}
	}
	else if(qName == "UpdateEveryFrame")
	{
		if(m_parsingVariable)
		{
			bool shouldUpdateEveryFrame = ((atts.value("value") == "true") ? true : false);
			m_currentVariable.shouldUpdateEveryFrame = shouldUpdateEveryFrame;
		}
	}
	else if(qName == "StandardValue")
	{
		if(m_parsingVariable)
		{
			QString standardValueName = atts.value("name");
			if(standardValueName == "DeltaTime")
			{
				m_currentVariable.standardValue = StandardValue::DeltaTime;
			}
			else if(standardValueName == "ElapsedTime")
			{
				m_currentVariable.standardValue = StandardValue::ElapsedTime;
			}

			m_currentVariable.isStandardValue = true;
			m_currentVariable.hasGuiControl = false;
		}
	}
	else if(qName == "GuiControl")
	{
		if(!m_parsingGuiControl)
		{
			m_parsingGuiControl = true;

			m_currentVariable.hasGuiControl = true;
			m_currentVariable.isStandardValue = false;
			m_currentVariable.standardValue = StandardValue::Invalid;

			QString type = atts.value("type");
			if(type == "CheckBox")
			{
				m_currentGuiControlDef.type = EffectVariableGuiControlType::CheckBox;
			}
			else if(type == "Slider")
			{
				m_currentGuiControlDef.type = EffectVariableGuiControlType::Slider;
			}
			else if(type == "RadioButtons")
			{
				m_currentGuiControlDef.type = EffectVariableGuiControlType::RadioButtons;
			}
		}
	}
	else if(qName == "Entry")
	{
		if(m_parsingGuiControl)
		{
			if(m_currentGuiControlDef.type == EffectVariableGuiControlType::RadioButtons)
			{
				EffectVariableRadioButtonsEntry entry;
				entry.text = atts.value("text");
				entry.isDefault = false;

				if(atts.index("default") != -1)
				{
					entry.isDefault = true;
				}

				m_currentGuiControlDef.radioButtons.entries.append(entry);
			}
		}
	}
	else if(qName == "Min")
	{
		if(m_currentGuiControlDef.type == EffectVariableGuiControlType::Slider)
		{
			m_currentGuiControlDef.slider.min = atts.value("value").toInt();
		}
	}
	else if(qName == "Max")
	{
		if(m_currentGuiControlDef.type == EffectVariableGuiControlType::Slider)
		{
			m_currentGuiControlDef.slider.max = atts.value("value").toInt();
		}
	}
	else if(qName == "Default")
	{
		if(m_currentGuiControlDef.type == EffectVariableGuiControlType::Slider)
		{
			m_currentGuiControlDef.slider.default = atts.value("value").toInt();
		}
		else if(m_currentGuiControlDef.type == EffectVariableGuiControlType::CheckBox)
		{
			m_currentGuiControlDef.checkBox.pressedByDefault = ((atts.value("value") == "true") ? true : false);
		}
	}
	else if(qName == "Text")
	{
		if(m_currentGuiControlDef.type == EffectVariableGuiControlType::CheckBox)
		{
			m_currentGuiControlDef.checkBox.text = atts.value("value");
		}
	}
	else if(qName == "Title")
	{
		if(m_currentGuiControlDef.type == EffectVariableGuiControlType::RadioButtons)
		{
			m_currentGuiControlDef.radioButtons.title = atts.value("value");
		}
		else if(m_currentGuiControlDef.type == EffectVariableGuiControlType::Slider)
		{
			m_currentGuiControlDef.slider.title = atts.value("value");
		}
	}
	else
	{
	}

	return true;
}

bool EffectLoader::endElement(const QString& namespaceURI, const QString& localName, const QString& qName)
{
	if(qName == "Variables")
	{
		if(m_variablesActive)
		{
			m_variablesActive = false;
			qDebug() << "Finished parsing variables.";
		}
	}
	else if(qName == "Float")
	{
		if(m_parsingVariable)
		{
			m_parsingVariable = false;
			m_variables.append(m_currentVariable);
		}
	}
	else if(qName == "Integer")
	{
		if(m_parsingVariable)
		{
			m_parsingVariable = false;
			m_variables.append(m_currentVariable);
		}
	}
	else if(qName == "GuiControl")
	{
		if(m_parsingGuiControl)
		{
			QString name = m_currentVariable.name;
			m_variableGuiControlsDefs.insert(std::make_pair(name, m_currentGuiControlDef));

			m_parsingGuiControl = false;
		}
	}
	else
	{
		if(m_parsingVariable)
		{
		}
	}

	return true;
}

bool EffectLoader::characters(const QString& ch)
{
	return true;
}